#!/bin/bash

is_systemd() {
    IS_SYSTEMD=`ps -e -o ppid,pid,comm | grep -E -i '^\s*0\s+1\s+systemd'`
    if [ -n "$IS_SYSTEMD" ] ; then
        return 0
    fi

    return 1
}

ME=`whoami`

CDPC_INS_DIR=/usr/local/cdpc
CDPC_DIR=/usr/local/cdpc
CDPC_WATCH=/tmp/cdpcd_watch
CDPC_LOADINFO=/tmp/cdpcd-load.log
CDPC_LOGDIR="$CDPC_DIR/logs"
CDPC_UAUTH="$CDPC_DIR/uauth"

SUDO=''

if [ "$EUID" -ne 0 ] ; then
    SUDO='sudo'
fi

if [ "$UID" -gt 0 ] ; then

    if [[ ! -d "$CDPC_DIR/uauth" ]] || [ ! -f "$CDPC_DIR/uauth/$ME" ] ; then
        echo "没有被授权，普通用户无法使用cdpc管理服务。（You are not authorized.）"
        exit 1
    fi

    CDPC_DIR="$HOME/.cdpc"
    CDPC_WATCH="$CDPC_DIR/watch"
    CDPC_LOADINFO="$CDPC_DIR/cdpcd-load.log"
    CDPC_LOGDIR="$CDPC_DIR/logs"
fi

if [ ! -d "$CDPC_DIR" ] ; then
    mkdir -p "$CDPC_DIR"
fi

CDPC_CONFIG="$CDPC_DIR/config"
CDPC_DISABLED_DIR="$CDPC_CONFIG/disabled"

if [ ! -d "$CDPC_CONFIG" ] ; then
    mkdir -p $CDPC_CONFIG
fi

if [ ! -d "$CDPC_LOGDIR" ] ; then
    mkdir -p "$CDPC_LOGDIR"
fi

if [ ! -d "$CDPC_WATCH" ] ; then
    mkdir -p $CDPC_WATCH
fi

if [ ! -d "$CDPC_DISABLED_DIR" ] ; then
    mkdir -p $CDPC_DISABLED_DIR
fi

CDPC_SERVER="$CDPC_DIR/webserver"

CDPC_SERVER_APP="$CDPC_SERVER/app.js"

ARGS=''

help () {
    if [ -f "/usr/local/cdpc/helpdoc" ] ; then
        man "/usr/local/cdpc/helpdoc"
    fi
}

parse_args () {
    if [ "$#" -gt 0 ] ; then 
        COUNT=0
        for a in $@ ; do
            let COUNT+=1
            if [ $COUNT -gt 1 ] ; then
                ARGS="$ARGS $a"
            fi
        done
    fi
}

check_args2_exit () {
    if [ "$1" -lt $2 ] ; then
        echo "less arguments."
        exit 1
    fi
}

handle_config () {
    case $1 in
        add)
            if [ ! -f "$2" ] ; then
                echo "$2 : file not exists"
                exit 1
            fi

            cp "$2" "$CDPC_CONFIG/"
            echo "$CDPC_CONFIG/$2" > "$CDPC_WATCH/load"
            ;;

        remove)
            if [ ! -f "$CDPC_CONFIG/$2" ] ; then
                echo "file not exists"
                exit 1
            fi
            rm "$CDPC_CONFIG/$2"
            ;;
        list)
            CFGLIST=`ls $CDPC_CONFIG`
            for c in $CFGLIST ; do
                echo $c
            done
            ;;
        show)
            CFGLIST=`ls $CDPC_CONFIG`
            for c in $CFGLIST ; do
                echo "$CDPC_CONFIG/$c:"
                cat -n "$CDPC_CONFIG/$c"
                echo "    "
            done
            ;;
    esac
}

check_has_app() {
    __HAS_COUNT=0
    _APP_STATE_DIR="$CDPC_WATCH/state"
    _APP_STATE_FILE="$_APP_STATE_DIR/$1"
    
    if [ ! -d "$_APP_STATE_DIR" ] ; then
        return 1
    fi

    if [ ! -f "$_APP_STATE_FILE" ] ; then
        echo "$1 not found!!"
        return 1
    fi

    return 0
}

real_remove_file() {
    if [ -f "$1" ] ; then
        rm $1
    fi
}

remove_file_delay() {
    sleep 0.05 && real_remove_file $1
}

# 通过has子命令查找是否存在应用。
# 只有超级用户才可以获取所有的应用状态并指定其他用户身份控制应用。
handle_app() {
    LIMIT_USER_ARGS=''
    if [ $EUID -ne 0 ] ; then
        LIMIT_USER_ARGS=" --limit-user $USER"
    fi

    HAS_RESULT=`$0 has-name $ARGS`

    if [ -z "$HAS_RESULT" ] ; then
        echo "$ARGS not found!" | awk '{$1=$1};1'
        exit 1
    fi

    for a in $HAS_RESULT; do
        MAP_NAME_CMD_FILE=`node $CDPC_INS_DIR/mapnametocmd.js $a -op $1`

        node $CDPC_INS_DIR/noticeApp.js $MAP_NAME_CMD_FILE
        if [ "$EUID" -eq 0 ] ; then
            #删除文件，避免问题
            if [ -f "$MAP_NAME_CMD_FILE" ] ; then
                remove_file_delay $MAP_NAME_CMD_FILE &
            fi
        fi
    done

    case $1 in
        disable)
            node $CDPC_INS_DIR/disable-or-enable.js disable $HAS_RESULT
            ;;

        enable)
            node $CDPC_INS_DIR/disable-or-enable.js enable $HAS_RESULT
            ;;
    esac

    node $CDPC_INS_DIR/get_app_state.js $1 $HAS_RESULT
}

handle_webserver() {
    case $1 in
        start)
            ;;

        stop)
            ;;

        restart)
            ;;

        pause)
            ;;
        
        resume)
            ;;
        *)
            echo "$1 : unknow command"
            return 1
            ;;
    esac

    echo cdpcd-web-server > $CDPC_WATCH/$1/cdpcd-web-server
}

handle_auth() {
    case $1 in
        add)
            ;;

        remove)
            ;;

        show)
            ;;

        *)
            echo "unknow command"
            exit 1
            ;;
    esac

    node /usr/local/cdpc/auth.js $ARGS
}

load_config() {
    echo $1 > $CDPC_WATCH/load
}

clear_logs() {
    LOGFILES=`ls $CDPC_LOGDIR`
    for f in $LOGFILES ; do
        if [ ! "$f" = "cdpcd.log" ] ; then
            rm "$CDPC_LOGDIR/$f"
        fi
    done
}

handle_log() {
    case $1 in
        clear)
            clear_logs
            ;;
        clearall)
            clear_logs
            > "$CDPC_LOGDIR/cdpcd.log"
            ;;
    esac
}

parse_args $@

case $1 in
    start)
        check_args2_exit $# 2
        handle_app start $ARGS
        ;;

    stop)
        check_args2_exit $# 2
        handle_app stop $ARGS
        ;;

    restart)
        check_args2_exit $# 2
        handle_app restart $ARGS
        ;;

    pause)
        check_args2_exit $# 2
        handle_app pause $ARGS
        ;;

    resume)
        check_args2_exit $# 2
        handle_app resume $ARGS
        ;;

    reload)
        date > $CDPC_WATCH/reload
        ;;

    remove)
        check_args2_exit $# 2
        handle_app remove $ARGS
        ;;

    safe-remove)
        check_args2_exit $# 2
        handle_app safeRemove $ARGS
        ;;

    disable)
        check_args2_exit $# 2
        handle_app disable $ARGS
        ;;

    enable)
        check_args2_exit $# 2
        handle_app enable $ARGS
        ;;

    load)
        if [ "$#" -lt 2 ] ; then
            load_config $CDPC_CONFIG
        else
            load_config $CDPC_CONFIG/$2
        fi
        ;;

    log)
        if [ "$#" -lt 2 ] ; then
            if [ -d "$CDPC_LOGDIR" ] ; then
                LOGFILES=`ls $CDPC_LOGDIR | sort`
                for f in $LOGFILES ; do
                    echo "$f:"
                    cat "$CDPC_LOGDIR/$f" -b
                done
            fi
            exit 0
        fi

        handle_log $2
        ;;

    args)
      echo $ARGS
      ;;

    has-name)
        STATUS_TEXT_RESULT=`$0 status --has --encode-json $ARGS`

        node $CDPC_INS_DIR/combine-status-result.js $STATUS_TEXT_RESULT --only-name
        ;;

    has-encode)
        STATUS_TEXT_RESULT=`$0 status --has --encode-json $ARGS`

        node $CDPC_INS_DIR/combine-status-result.js $STATUS_TEXT_RESULT --encode-json
        ;;

    has)
        STATUS_TEXT_RESULT=`$0 status --has --encode-json $ARGS`

        node $CDPC_INS_DIR/combine-status-result.js $STATUS_TEXT_RESULT
        ;;

    status)
        node $CDPC_INS_DIR/outstatus.js $CDPC_LOADINFO $ARGS --user $USER
        if [ "$UID" -eq 0 ] ; then
            if [ -d "$CDPC_UAUTH" ] ; then
                UAULIST=`ls $CDPC_UAUTH`
                UCDPCD_LOAD=''
                for u in $UAULIST ; do
                    UHOMEDIR=`cat $CDPC_UAUTH/$u`
                    UCDPCD_LOAD="$UHOMEDIR/.cdpc/cdpcd-load.log"
                    if [ -f "$UCDPCD_LOAD" ] ; then
                        node $CDPC_INS_DIR/outstatus.js $UCDPCD_LOAD $ARGS --user $u
                    fi
                done
            fi
        fi
        ;;

    has-app)
        for a in $ARGS ; do
            if check_has_app $a ; then
                echo "has $a"
            fi
        done
        ;;
    
    #start stop restart
    webserver)
        check_args2_exit $# 2
        if [ "$UID" -gt 0 ] ; then
            echo "deny!!"
            exit 1
        fi

        handle_webserver $2
        ;;

    config)
        if [[ $# -gt 1 ]] && [[ "$2" = "show" ]] ; then
            handle_config show
            exit 0
        fi

        check_args2_exit $# 3
        handle_config $2 $3
        ;;

    #用户授权
    auth)
        if [[ $# -lt 2 ]] && [[ "$UID" -gt 0 ]] ; then
            if [ ! -f "/usr/local/cdpc/uauth/$ME" ] ; then
                echo "!!还没有被授权(You are not authorized.)"
            else
                echo "已被授权(You have be authorized.)"
            fi

            exit 0
        fi

        if [ "$UID" -gt 0 ] ; then
            echo "deny!!"
            exit 1
        fi

        if [ $# -lt 2 ] ; then
            UAUTH_PATH="/usr/local/cdpc/uauth"

            if [ ! -d "$UAUTH_PATH" ] ; then
                echo 'There is no user auth.'
            else
                ls $UAUTH_PATH
            fi

            exit 0
        fi

        #check_args2_exit $# 3

        #[add|remove] [USER]
        handle_auth $ARGS
        ;;

    help)
        help
        ;;
    
    'service-stop')
        if is_systemd ; then
            $SUDO systemctl stop cdpcd.service
        else
            $SUDO /etc/init.d/cdpc stop
        fi
        ;;

    'service-start')
        if is_systemd ; then
            $SUDO systemctl start cdpcd.service
        else
            $SUDO /etc/init.d/cdpc start
        fi
        ;;

    'service-restart')
        if is_systemd ; then
            $SUDO systemctl restart cdpcd.service
        else
            $SUDO /etc/init.d/cdpc restart
        fi
        ;;

    *)
        printf "\x1b[2;36m使用cdpc help查看帮助文档\n\x1b[0m"
        echo "快速使用提示："
        echo "  cdpc status 查看应用状态"
        echo "  cdpc config add [文件路径] 添加配置文件"
        echo "  cdpc config show 显示配置文件详情"
        echo "  cdpc config remove [配置文件名称] 移除配置文件"
        echo "  cdpc start  [应用名称] 启动应用"
        echo "  cdpc stop   [应用名称] 停止应用"
        echo "  cdpc pause  [应用名称] 暂停应用"
        echo "  cdpc resume  [应用名称] 恢复暂停的应用"
        echo "  cdpc restart [应用名称] 重启应用"
        echo "  cdpc auth 查看自己是否被授权/查看授权信息"
        echo "  cdpc service-start 启动cdpcd服务"
        echo "  cdpc service-stop 停止cdpcd服务"
        echo "  cdpc service-restart 重启cdpcd服务"
        echo "示例："
        echo "  cdpc stop --all"
        echo "  cdpc restart app1 app2"

        exit 0
        ;;
esac
